home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / palette.c < prev    next >
C/C++ Source or Header  |  2000-05-13  |  52KB  |  1,844 lines

  1. /******************************************************************************
  2.  
  3.   palette.c
  4.  
  5.   Palette handling functions.
  6.  
  7.   There are several levels of abstraction in the way MAME handles the palette,
  8.   and several display modes which can be used by the drivers.
  9.  
  10.   Palette
  11.   -------
  12.   Note: in the following text, "color" refers to a color in the emulated
  13.   game's virtual palette. For example, a game might be able to display 1024
  14.   colors at the same time. If the game uses RAM to change the available
  15.   colors, the term "palette" refers to the colors available at any given time,
  16.   not to the whole range of colors which can be produced by the hardware. The
  17.   latter is referred to as "color space".
  18.   The term "pen" refers to one of the maximum MAX_PENS colors that can be
  19.   used to generate the display. PC users might want to think of them as the
  20.   colors available in VGA, but be warned: the mapping of MAME pens to the VGA
  21.   registers is not 1:1, so MAME's pen 10 will not necessarily be mapped to
  22.   VGA's color #10 (actually this is never the case). This is done to ensure
  23.   portability, since on some systems it is not possible to do a 1:1 mapping.
  24.  
  25.   So, to summarize, the three layers of palette abstraction are:
  26.  
  27.   P1) The game virtual palette (the "colors")
  28.   P2) MAME's MAX_PENS colors palette (the "pens")
  29.   P3) The OS specific hardware color registers (the "OS specific pens")
  30.  
  31.   The array Machine->pens is a lookup table which maps game colors to OS
  32.   specific pens (P1 to P3). When you are working on bitmaps at the pixel level,
  33.   *always* use Machine->pens to map the color numbers. *Never* use constants.
  34.   For example if you want to make pixel (x,y) of color 3, do:
  35.   bitmap->line[y][x] = Machine->pens[3];
  36.  
  37.  
  38.   Lookup table
  39.   ------------
  40.   Palettes are only half of the story. To map the gfx data to colors, the
  41.   graphics routines use a lookup table. For example if we have 4bpp tiles,
  42.   which can have 256 different color codes, the lookup table for them will have
  43.   256 * 2^4 = 4096 elements. For games using a palette RAM, the lookup table is
  44.   usually a 1:1 map. For games using PROMs, the lookup table is often larger
  45.   than the palette itself so for example the game can display 256 colors out
  46.   of a palette of 16.
  47.  
  48.   The palette and the lookup table are initialized to default values by the
  49.   main core, but can be initialized by the driver using the function
  50.   MachineDriver->vh_init_palette(). For games using palette RAM, that
  51.   function is usually not needed, and the lookup table can be set up by
  52.   properly initializing the color_codes_start and total_color_codes fields in
  53.   the GfxDecodeInfo array.
  54.   When vh_init_palette() initializes the lookup table, it maps gfx codes
  55.   to game colors (P1 above). The lookup table will be converted by the core to
  56.   map to OS specific pens (P3 above), and stored in Machine->remapped_colortable.
  57.  
  58.  
  59.   Display modes
  60.   -------------
  61.   The available display modes can be summarized in four categories:
  62.   1) Static palette. Use this for games which use PROMs for color generation.
  63.      The palette is initialized by vh_init_palette(), and never changed
  64.      again.
  65.   2) Dynamic palette. Use this for games which use RAM for color generation and
  66.      have no more than MAX_PENS colors in the palette. The palette can be
  67.      dynamically modified by the driver using the function
  68.      palette_change_color(). MachineDriver->video_attributes must contain the
  69.      flag VIDEO_MODIFIES_PALETTE.
  70.   3) Dynamic shrinked palette. Use this for games which use RAM for color
  71.      generation and have more than MAX_PENS colors in the palette. The palette
  72.      can be dynamically modified by the driver using the function
  73.      palette_change_color(). MachineDriver->video_attributes must contain the
  74.      flag VIDEO_MODIFIES_PALETTE.
  75.      The difference with case 2) above is that the driver must do some
  76.      additional work to allow for palette reduction without loss of quality.
  77.      The function palette_recalc() must be called every frame before doing any
  78.      rendering. The palette_used_colors array can be changed to precisely
  79.      indicate to the function which of the game colors are used, so it can pick
  80.      only the needed colors, and make the palette fit into MAX_PENS colors.
  81.      Colors can also be marked as "transparent".
  82.      The return code of palette_recalc() tells the driver whether the lookup
  83.      table has changed, and therefore whether a screen refresh is needed. Note
  84.      that this only applies to colors which were used in the previous frame:
  85.      that's why palette_recalc() must be called before ANY rendering takes
  86.      place.
  87.   4) 16-bit color. This should only be used for games which use more than
  88.      MAX_PENS colors at a time. It is slower than the other modes, so it should
  89.      be avoided whenever possible. Transparency support is limited.
  90.      MachineDriver->video_attributes must contain VIDEO_MODIFIES_PALETTE, and
  91.      GameDriver->flags GAME_REQUIRES_16BIT.
  92.  
  93.   The dynamic shrinking of the palette works this way: as colors are requested,
  94.   they are associated to a pen. When a color is no longer needed, the pen is
  95.   freed and can be used for another color. When the code runs out of free pens,
  96.   it compacts the palette, putting together colors with the same RGB
  97.   components, then starts again to allocate pens for each new color. The bottom
  98.   line of all this is that the pen assignment will automatically adapt to the
  99.   game needs, and colors which change often will be assigned an exclusive pen,
  100.   which can be modified using the video cards hardware registers without need
  101.   for a screen refresh.
  102.   The important difference between cases 3) and 4) is that in 3), color cycling
  103.   (which many games use) is essentially free, while in 4) every palette change
  104.   requires a screen refresh. The color quality in 3) is also better than in 4)
  105.   if the game uses more than 5 bits per color component. For testing purposes,
  106.   you can switch between the two modes by just adding/removing the
  107.   GAME_REQUIRES_16BIT flag (but be warned about the limited transparency
  108.   support in 16-bit mode).
  109.  
  110. ******************************************************************************/
  111.  
  112. #include "driver.h"
  113. #include "artwork.h"
  114.  
  115.  
  116. #define VERBOSE 0
  117.  
  118.  
  119. static unsigned char *game_palette;    /* RGB palette as set by the driver. */
  120. static unsigned char *new_palette;    /* changes to the palette are stored here before */
  121.                             /* being moved to game_palette by palette_recalc() */
  122. static unsigned char *palette_dirty;
  123. /* arrays which keep track of colors actually used, to help in the palette shrinking. */
  124. unsigned char *palette_used_colors;
  125. static unsigned char *old_used_colors;
  126. static int *pen_visiblecount,*pen_cachedcount;
  127. static unsigned char *just_remapped;    /* colors which have been remapped in this frame, */
  128.                                         /* returned by palette_recalc() */
  129.  
  130. static int use_16bit;
  131. #define NO_16BIT            0
  132. #define STATIC_16BIT        1
  133. #define PALETTIZED_16BIT    2
  134.  
  135. static int total_shrinked_pens;
  136. unsigned short *shrinked_pens;
  137. static unsigned char *shrinked_palette;
  138. static unsigned short *palette_map;    /* map indexes from game_palette to shrinked_palette */
  139. static unsigned short pen_usage_count[DYNAMIC_MAX_PENS];
  140.  
  141. unsigned short palette_transparent_pen;
  142. int palette_transparent_color;
  143.  
  144.  
  145. #define BLACK_PEN        0
  146. #define TRANSPARENT_PEN    1
  147. #define RESERVED_PENS    2
  148.  
  149. #define PALETTE_COLOR_NEEDS_REMAP 0x80
  150.  
  151. /* helper macro for 16-bit mode */
  152. #define rgbpenindex(r,g,b) ((Machine->scrbitmap->depth==16) ? ((((r)>>3)<<10)+(((g)>>3)<<5)+((b)>>3)) : ((((r)>>5)<<5)+(((g)>>5)<<2)+((b)>>6)))
  153.  
  154.  
  155. unsigned short *palette_shadow_table;
  156. unsigned short *palette_highlight_table;
  157.  
  158. void overlay_remap(void);
  159.  
  160.  
  161.  
  162. int palette_start(void)
  163. {
  164.     int i,num;
  165.  
  166.  
  167.     game_palette = malloc(3 * Machine->drv->total_colors * sizeof(unsigned char));
  168.     palette_map = malloc(Machine->drv->total_colors * sizeof(unsigned short));
  169.     if (Machine->drv->color_table_len)
  170.     {
  171.         Machine->game_colortable = malloc(Machine->drv->color_table_len * sizeof(unsigned short));
  172.         Machine->remapped_colortable = malloc(Machine->drv->color_table_len * sizeof(unsigned short));
  173.     }
  174.     else Machine->game_colortable = Machine->remapped_colortable = 0;
  175.  
  176.     if (Machine->color_depth == 16 || (Machine->gamedrv->flags & GAME_REQUIRES_16BIT))
  177.     {
  178.         if (Machine->color_depth == 8 || Machine->drv->total_colors > 65532)
  179.             use_16bit = STATIC_16BIT;
  180.         else
  181.             use_16bit = PALETTIZED_16BIT;
  182.     }
  183.     else
  184.         use_16bit = NO_16BIT;
  185.  
  186.     switch (use_16bit)
  187.     {
  188.         case NO_16BIT:
  189.             if (Machine->drv->video_attributes & VIDEO_MODIFIES_PALETTE)
  190.                 total_shrinked_pens = DYNAMIC_MAX_PENS;
  191.             else
  192.                 total_shrinked_pens = STATIC_MAX_PENS;
  193.             break;
  194.         case STATIC_16BIT:
  195.             total_shrinked_pens = 32768;
  196.             break;
  197.         case PALETTIZED_16BIT:
  198.             total_shrinked_pens = Machine->drv->total_colors + RESERVED_PENS;
  199.             break;
  200.     }
  201.  
  202.     shrinked_pens = malloc(total_shrinked_pens * sizeof(short));
  203.     shrinked_palette = malloc(3 * total_shrinked_pens * sizeof(unsigned char));
  204.  
  205.     Machine->pens = malloc(Machine->drv->total_colors * sizeof(short));
  206.  
  207.     if ((Machine->drv->video_attributes & VIDEO_MODIFIES_PALETTE))
  208.     {
  209.         /* if the palette changes dynamically, */
  210.         /* we'll need the usage arrays to help in shrinking. */
  211.         palette_used_colors = malloc((1+1+1+3+1) * Machine->drv->total_colors * sizeof(unsigned char));
  212.         pen_visiblecount = malloc(2 * Machine->drv->total_colors * sizeof(int));
  213.  
  214.         if (palette_used_colors == 0 || pen_visiblecount == 0)
  215.         {
  216.             palette_stop();
  217.             return 1;
  218.         }
  219.  
  220.         old_used_colors = palette_used_colors + Machine->drv->total_colors * sizeof(unsigned char);
  221.         just_remapped = old_used_colors + Machine->drv->total_colors * sizeof(unsigned char);
  222.         new_palette = just_remapped + Machine->drv->total_colors * sizeof(unsigned char);
  223.         palette_dirty = new_palette + 3*Machine->drv->total_colors * sizeof(unsigned char);
  224.         memset(palette_used_colors,PALETTE_COLOR_USED,Machine->drv->total_colors * sizeof(unsigned char));
  225.         memset(old_used_colors,PALETTE_COLOR_UNUSED,Machine->drv->total_colors * sizeof(unsigned char));
  226.         memset(palette_dirty,0,Machine->drv->total_colors * sizeof(unsigned char));
  227.         pen_cachedcount = pen_visiblecount + Machine->drv->total_colors;
  228.         memset(pen_visiblecount,0,Machine->drv->total_colors * sizeof(int));
  229.         memset(pen_cachedcount,0,Machine->drv->total_colors * sizeof(int));
  230.     }
  231.     else palette_used_colors = old_used_colors = just_remapped = new_palette = palette_dirty = 0;
  232.  
  233.     if (Machine->color_depth == 8) num = 256;
  234.     else num = 65536;
  235.     palette_shadow_table = malloc(2 * num * sizeof(unsigned short));
  236.     if (palette_shadow_table == 0)
  237.     {
  238.         palette_stop();
  239.         return 1;
  240.     }
  241.     palette_highlight_table = palette_shadow_table + num;
  242.     for (i = 0;i < num;i++)
  243.         palette_shadow_table[i] = palette_highlight_table[i] = i;
  244.  
  245.     if ((Machine->drv->color_table_len && (Machine->game_colortable == 0 || Machine->remapped_colortable == 0))
  246.             || game_palette == 0 ||    palette_map == 0
  247.             || shrinked_pens == 0 || shrinked_palette == 0 || Machine->pens == 0)
  248.     {
  249.         palette_stop();
  250.         return 1;
  251.     }
  252.  
  253.     return 0;
  254. }
  255.  
  256. void palette_stop(void)
  257. {
  258.     free(palette_used_colors);
  259.     palette_used_colors = old_used_colors = just_remapped = new_palette = palette_dirty = 0;
  260.     free(pen_visiblecount);
  261.     pen_visiblecount = 0;
  262.     free(game_palette);
  263.     game_palette = 0;
  264.     free(palette_map);
  265.     palette_map = 0;
  266.     free(Machine->game_colortable);
  267.     Machine->game_colortable = 0;
  268.     free(Machine->remapped_colortable);
  269.     Machine->remapped_colortable = 0;
  270.     free(shrinked_pens);
  271.     shrinked_pens = 0;
  272.     free(shrinked_palette);
  273.     shrinked_palette = 0;
  274.     free(Machine->pens);
  275.     Machine->pens = 0;
  276.     free(palette_shadow_table);
  277.     palette_shadow_table = 0;
  278. }
  279.  
  280.  
  281.  
  282. int palette_init(void)
  283. {
  284.     int i;
  285.  
  286.  
  287.     /* We initialize the palette and colortable to some default values so that */
  288.     /* drivers which dynamically change the palette don't need a vh_init_palette() */
  289.     /* function (provided the default color table fits their needs). */
  290.  
  291.     for (i = 0;i < Machine->drv->total_colors;i++)
  292.     {
  293.         game_palette[3*i + 0] = ((i & 1) >> 0) * 0xff;
  294.         game_palette[3*i + 1] = ((i & 2) >> 1) * 0xff;
  295.         game_palette[3*i + 2] = ((i & 4) >> 2) * 0xff;
  296.     }
  297.  
  298.     /* Preload the colortable with a default setting, following the same */
  299.     /* order of the palette. The driver can overwrite this in */
  300.     /* vh_init_palette() */
  301.     for (i = 0;i < Machine->drv->color_table_len;i++)
  302.         Machine->game_colortable[i] = i % Machine->drv->total_colors;
  303.  
  304.     /* by default we use -1 to identify the transparent color, the driver */
  305.     /* can modify this. */
  306.     palette_transparent_color = -1;
  307.  
  308.     /* now the driver can modify the default values if it wants to. */
  309.     if (Machine->drv->vh_init_palette)
  310.         (*Machine->drv->vh_init_palette)(game_palette,Machine->game_colortable,memory_region(REGION_PROMS));
  311.  
  312.  
  313.     switch (use_16bit)
  314.     {
  315.         case NO_16BIT:
  316.         {
  317.             /* initialize shrinked palette to all black */
  318.             for (i = 0;i < total_shrinked_pens;i++)
  319.             {
  320.                 shrinked_palette[3*i + 0] =
  321.                 shrinked_palette[3*i + 1] =
  322.                 shrinked_palette[3*i + 2] = 0;
  323.             }
  324.  
  325.             if (Machine->drv->video_attributes & VIDEO_MODIFIES_PALETTE)
  326.             {
  327.                 /* initialize pen usage counters */
  328.                 for (i = 0;i < DYNAMIC_MAX_PENS;i++)
  329.                     pen_usage_count[i] = 0;
  330.  
  331.                 /* allocate two fixed pens at the beginning: */
  332.                 /* transparent black */
  333.                 pen_usage_count[TRANSPARENT_PEN] = 1;    /* so the pen will not be reused */
  334.  
  335.                 /* non transparent black */
  336.                 pen_usage_count[BLACK_PEN] = 1;
  337.  
  338.                 /* create some defaults associations of game colors to shrinked pens. */
  339.                 /* They will be dynamically modified at run time. */
  340.                 for (i = 0;i < Machine->drv->total_colors;i++)
  341.                     palette_map[i] = (i & 7) + 8;
  342.  
  343.                 if (osd_allocate_colors(total_shrinked_pens,shrinked_palette,shrinked_pens,1))
  344.                     return 1;
  345.             }
  346.             else
  347.             {
  348.                 int j,used;
  349.  
  350.  
  351. logerror("shrinking %d colors palette...\n",Machine->drv->total_colors);
  352.  
  353.                 /* shrink palette to fit */
  354.                 used = 0;
  355.  
  356.                 for (i = 0;i < Machine->drv->total_colors;i++)
  357.                 {
  358.                     for (j = 0;j < used;j++)
  359.                     {
  360.                         if (    shrinked_palette[3*j + 0] == game_palette[3*i + 0] &&
  361.                                 shrinked_palette[3*j + 1] == game_palette[3*i + 1] &&
  362.                                 shrinked_palette[3*j + 2] == game_palette[3*i + 2])
  363.                             break;
  364.                     }
  365.  
  366.                     palette_map[i] = j;
  367.  
  368.                     if (j == used)
  369.                     {
  370.                         used++;
  371.                         if (used > total_shrinked_pens)
  372.                         {
  373.                             used = total_shrinked_pens;
  374.                             palette_map[i] = total_shrinked_pens-1;
  375.                             usrintf_showmessage("cannot shrink static palette");
  376. logerror("error: ran out of free pens to shrink the palette.\n");
  377.                         }
  378.                         else
  379.                         {
  380.                             shrinked_palette[3*j + 0] = game_palette[3*i + 0];
  381.                             shrinked_palette[3*j + 1] = game_palette[3*i + 1];
  382.                             shrinked_palette[3*j + 2] = game_palette[3*i + 2];
  383.                         }
  384.                     }
  385.                 }
  386.  
  387. logerror("shrinked palette uses %d colors\n",used);
  388.  
  389.                 if (osd_allocate_colors(used,shrinked_palette,shrinked_pens,0))
  390.                     return 1;
  391.             }
  392.  
  393.  
  394.             for (i = 0;i < Machine->drv->total_colors;i++)
  395.                 Machine->pens[i] = shrinked_pens[palette_map[i]];
  396.  
  397.             palette_transparent_pen = shrinked_pens[TRANSPARENT_PEN];    /* for dynamic palette games */
  398.         }
  399.         break;
  400.  
  401.         case STATIC_16BIT:
  402.         {
  403.             unsigned char *p = shrinked_palette;
  404.             int r,g,b;
  405.  
  406.             if (Machine->scrbitmap->depth == 16)
  407.             {
  408.                 for (r = 0;r < 32;r++)
  409.                 {
  410.                     for (g = 0;g < 32;g++)
  411.                     {
  412.                         for (b = 0;b < 32;b++)
  413.                         {
  414.                             *p++ = (r << 3) | (r >> 2);
  415.                             *p++ = (g << 3) | (g >> 2);
  416.                             *p++ = (b << 3) | (b >> 2);
  417.                         }
  418.                     }
  419.                 }
  420.  
  421.                 if (osd_allocate_colors(32768,shrinked_palette,shrinked_pens,0))
  422.                     return 1;
  423.             }
  424.             else
  425.             {
  426.                 for (r = 0;r < 8;r++)
  427.                 {
  428.                     for (g = 0;g < 8;g++)
  429.                     {
  430.                         for (b = 0;b < 4;b++)
  431.                         {
  432.                             *p++ = (r << 5) | (r << 2) | (r >> 1);
  433.                             *p++ = (g << 5) | (g << 2) | (g >> 1);
  434.                             *p++ = (b << 6) | (b << 4) | (b << 2) | b;
  435.                         }
  436.                     }
  437.                 }
  438.  
  439.                 if (osd_allocate_colors(256,shrinked_palette,shrinked_pens,0))
  440.                     return 1;
  441.             }
  442.  
  443.             for (i = 0;i < Machine->drv->total_colors;i++)
  444.             {
  445.                 r = game_palette[3*i + 0];
  446.                 g = game_palette[3*i + 1];
  447.                 b = game_palette[3*i + 2];
  448.  
  449.                 Machine->pens[i] = shrinked_pens[rgbpenindex(r,g,b)];
  450.             }
  451.  
  452.             palette_transparent_pen = shrinked_pens[0];    /* we are forced to use black for the transparent pen */
  453.         }
  454.         break;
  455.  
  456.         case PALETTIZED_16BIT:
  457.         {
  458.             for (i = 0;i < RESERVED_PENS;i++)
  459.             {
  460.                 shrinked_palette[3*i + 0] =
  461.                 shrinked_palette[3*i + 1] =
  462.                 shrinked_palette[3*i + 2] = 0;
  463.             }
  464.  
  465.             for (i = 0;i < Machine->drv->total_colors;i++)
  466.             {
  467.                 shrinked_palette[3*(i+RESERVED_PENS) + 0] = game_palette[3*i + 0];
  468.                 shrinked_palette[3*(i+RESERVED_PENS) + 1] = game_palette[3*i + 1];
  469.                 shrinked_palette[3*(i+RESERVED_PENS) + 2] = game_palette[3*i + 2];
  470.             }
  471.  
  472.             if (osd_allocate_colors(total_shrinked_pens,shrinked_palette,shrinked_pens,(Machine->drv->video_attributes & VIDEO_MODIFIES_PALETTE)))
  473.                 return 1;
  474.  
  475.             for (i = 0;i < Machine->drv->total_colors;i++)
  476.                 Machine->pens[i] = shrinked_pens[i + RESERVED_PENS];
  477.  
  478.             palette_transparent_pen = shrinked_pens[TRANSPARENT_PEN];    /* for dynamic palette games */
  479.         }
  480.         break;
  481.     }
  482.  
  483.     for (i = 0;i < Machine->drv->color_table_len;i++)
  484.     {
  485.         int color = Machine->game_colortable[i];
  486.  
  487.         /* check for invalid colors set by Machine->drv->vh_init_palette */
  488.         if (color < Machine->drv->total_colors)
  489.             Machine->remapped_colortable[i] = Machine->pens[color];
  490.         else
  491.             usrintf_showmessage("colortable[%d] (=%d) out of range (total_colors = %d)",
  492.                     i,color,Machine->drv->total_colors);
  493.     }
  494.  
  495.     return 0;
  496. }
  497.  
  498.  
  499.  
  500. INLINE void palette_change_color_16_static(int color,unsigned char red,unsigned char green,unsigned char blue)
  501. {
  502.     if (color == palette_transparent_color)
  503.     {
  504.         int i;
  505.  
  506.  
  507.         palette_transparent_pen = shrinked_pens[rgbpenindex(red,green,blue)];
  508.  
  509.         if (color == -1) return;    /* by default, palette_transparent_color is -1 */
  510.  
  511.         for (i = 0;i < Machine->drv->total_colors;i++)
  512.         {
  513.             if ((old_used_colors[i] & (PALETTE_COLOR_VISIBLE | PALETTE_COLOR_TRANSPARENT_FLAG))
  514.                     == (PALETTE_COLOR_VISIBLE | PALETTE_COLOR_TRANSPARENT_FLAG))
  515.                 old_used_colors[i] |= PALETTE_COLOR_NEEDS_REMAP;
  516.         }
  517.     }
  518.  
  519.     if (    game_palette[3*color + 0] == red &&
  520.             game_palette[3*color + 1] == green &&
  521.             game_palette[3*color + 2] == blue)
  522.         return;
  523.  
  524.     game_palette[3*color + 0] = red;
  525.     game_palette[3*color + 1] = green;
  526.     game_palette[3*color + 2] = blue;
  527.  
  528.     if (old_used_colors[color] & PALETTE_COLOR_VISIBLE)
  529.         /* we'll have to reassign the color in palette_recalc() */
  530.         old_used_colors[color] |= PALETTE_COLOR_NEEDS_REMAP;
  531. }
  532.  
  533. INLINE void palette_change_color_16_palettized(int color,unsigned char red,unsigned char green,unsigned char blue)
  534. {
  535.     if (color == palette_transparent_color)
  536.     {
  537.         osd_modify_pen(palette_transparent_pen,red,green,blue);
  538.  
  539.         if (color == -1) return;    /* by default, palette_transparent_color is -1 */
  540.     }
  541.  
  542.     if (    game_palette[3*color + 0] == red &&
  543.             game_palette[3*color + 1] == green &&
  544.             game_palette[3*color + 2] == blue)
  545.         return;
  546.  
  547.     /* Machine->pens[color] might have been remapped to transparent_pen, so I */
  548.     /* use shrinked_pens[] directly */
  549.     osd_modify_pen(shrinked_pens[color + RESERVED_PENS],red,green,blue);
  550.     game_palette[3*color + 0] = red;
  551.     game_palette[3*color + 1] = green;
  552.     game_palette[3*color + 2] = blue;
  553. }
  554.  
  555. INLINE void palette_change_color_8(int color,unsigned char red,unsigned char green,unsigned char blue)
  556. {
  557.     int pen;
  558.  
  559.     if (color == palette_transparent_color)
  560.     {
  561.         osd_modify_pen(palette_transparent_pen,red,green,blue);
  562.  
  563.         if (color == -1) return;    /* by default, palette_transparent_color is -1 */
  564.     }
  565.  
  566.     if (    game_palette[3*color + 0] == red &&
  567.             game_palette[3*color + 1] == green &&
  568.             game_palette[3*color + 2] == blue)
  569.     {
  570.         palette_dirty[color] = 0;
  571.         return;
  572.     }
  573.  
  574.     pen = palette_map[color];
  575.  
  576.     /* if the color was used, mark it as dirty, we'll change it in palette_recalc() */
  577.     if (old_used_colors[color] & PALETTE_COLOR_VISIBLE)
  578.     {
  579.         new_palette[3*color + 0] = red;
  580.         new_palette[3*color + 1] = green;
  581.         new_palette[3*color + 2] = blue;
  582.         palette_dirty[color] = 1;
  583.     }
  584.     /* otherwise, just update the array */
  585.     else
  586.     {
  587.         game_palette[3*color + 0] = red;
  588.         game_palette[3*color + 1] = green;
  589.         game_palette[3*color + 2] = blue;
  590.     }
  591. }
  592.  
  593. void palette_change_color(int color,unsigned char red,unsigned char green,unsigned char blue)
  594. {
  595.     if ((Machine->drv->video_attributes & VIDEO_MODIFIES_PALETTE) == 0)
  596.     {
  597. logerror("Error: palette_change_color() called, but VIDEO_MODIFIES_PALETTE not set.\n");
  598.         return;
  599.     }
  600.  
  601.     if (color >= Machine->drv->total_colors)
  602.     {
  603. logerror("error: palette_change_color() called with color %d, but only %d allocated.\n",color,Machine->drv->total_colors);
  604.         return;
  605.     }
  606.  
  607.     switch (use_16bit)
  608.     {
  609.         case NO_16BIT:
  610.             palette_change_color_8(color,red,green,blue);
  611.             break;
  612.         case STATIC_16BIT:
  613.             palette_change_color_16_static(color,red,green,blue);
  614.             break;
  615.         case PALETTIZED_16BIT:
  616.             palette_change_color_16_palettized(color,red,green,blue);
  617.             break;
  618.     }
  619. }
  620.  
  621.  
  622.  
  623.  
  624. void palette_increase_usage_count(int table_offset,unsigned int usage_mask,int color_flags)
  625. {
  626.     /* if we are not dynamically reducing the palette, return immediately. */
  627.     if (palette_used_colors == 0) return;
  628.  
  629.     while (usage_mask)
  630.     {
  631.         if (usage_mask & 1)
  632.         {
  633.             if (color_flags & PALETTE_COLOR_VISIBLE)
  634.                 pen_visiblecount[Machine->game_colortable[table_offset]]++;
  635.             if (color_flags & PALETTE_COLOR_CACHED)
  636.                 pen_cachedcount[Machine->game_colortable[table_offset]]++;
  637.         }
  638.         table_offset++;
  639.         usage_mask >>= 1;
  640.     }
  641. }
  642.  
  643. void palette_decrease_usage_count(int table_offset,unsigned int usage_mask,int color_flags)
  644. {
  645.     /* if we are not dynamically reducing the palette, return immediately. */
  646.     if (palette_used_colors == 0) return;
  647.  
  648.     while (usage_mask)
  649.     {
  650.         if (usage_mask & 1)
  651.         {
  652.             if (color_flags & PALETTE_COLOR_VISIBLE)
  653.                 pen_visiblecount[Machine->game_colortable[table_offset]]--;
  654.             if (color_flags & PALETTE_COLOR_CACHED)
  655.                 pen_cachedcount[Machine->game_colortable[table_offset]]--;
  656.         }
  657.         table_offset++;
  658.         usage_mask >>= 1;
  659.     }
  660. }
  661.  
  662. void palette_increase_usage_countx(int table_offset,int num_pens,const unsigned char *pen_data,int color_flags)
  663. {
  664.     char flag[256];
  665.     memset(flag,0,256);
  666.  
  667.     while (num_pens--)
  668.     {
  669.         int pen = pen_data[num_pens];
  670.         if (flag[pen] == 0)
  671.         {
  672.             if (color_flags & PALETTE_COLOR_VISIBLE)
  673.                 pen_visiblecount[Machine->game_colortable[table_offset+pen]]++;
  674.             if (color_flags & PALETTE_COLOR_CACHED)
  675.                 pen_cachedcount[Machine->game_colortable[table_offset+pen]]++;
  676.             flag[pen] = 1;
  677.         }
  678.     }
  679. }
  680.  
  681. void palette_decrease_usage_countx(int table_offset, int num_pens, const unsigned char *pen_data,int color_flags)
  682. {
  683.     char flag[256];
  684.     memset(flag,0,256);
  685.  
  686.     while (num_pens--)
  687.     {
  688.         int pen = pen_data[num_pens];
  689.         if (flag[pen] == 0)
  690.         {
  691.             if (color_flags & PALETTE_COLOR_VISIBLE)
  692.                 pen_visiblecount[Machine->game_colortable[table_offset+pen]]--;
  693.             if (color_flags & PALETTE_COLOR_CACHED)
  694.                 pen_cachedcount[Machine->game_colortable[table_offset+pen]]--;
  695.             flag[pen] = 1;
  696.         }
  697.     }
  698. }
  699.  
  700. void palette_init_used_colors(void)
  701. {
  702.     int pen;
  703.  
  704.  
  705.     /* if we are not dynamically reducing the palette, return immediately. */
  706.     if (palette_used_colors == 0) return;
  707.  
  708.     memset(palette_used_colors,PALETTE_COLOR_UNUSED,Machine->drv->total_colors * sizeof(unsigned char));
  709.  
  710.     for (pen = 0;pen < Machine->drv->total_colors;pen++)
  711.     {
  712.         if (pen_visiblecount[pen]) palette_used_colors[pen] |= PALETTE_COLOR_VISIBLE;
  713.         if (pen_cachedcount[pen]) palette_used_colors[pen] |= PALETTE_COLOR_CACHED;
  714.     }
  715. }
  716.  
  717.  
  718.  
  719.  
  720. static unsigned char rgb6_to_pen[64][64][64];
  721.  
  722. static void build_rgb_to_pen(void)
  723. {
  724.     int i,rr,gg,bb;
  725.  
  726.     memset(rgb6_to_pen,DYNAMIC_MAX_PENS,sizeof(rgb6_to_pen));
  727.     rgb6_to_pen[0][0][0] = BLACK_PEN;
  728.  
  729.     for (i = 0;i < DYNAMIC_MAX_PENS;i++)
  730.     {
  731.         if (pen_usage_count[i] > 0)
  732.         {
  733.             rr = shrinked_palette[3*i + 0] >> 2;
  734.             gg = shrinked_palette[3*i + 1] >> 2;
  735.             bb = shrinked_palette[3*i + 2] >> 2;
  736.  
  737.             if (rgb6_to_pen[rr][gg][bb] == DYNAMIC_MAX_PENS)
  738.             {
  739.                 int j,max;
  740.  
  741.                 rgb6_to_pen[rr][gg][bb] = i;
  742.                 max = pen_usage_count[i];
  743.  
  744.                 /* to reduce flickering during remaps, find the pen used by most colors */
  745.                 for (j = i+1;j < DYNAMIC_MAX_PENS;j++)
  746.                 {
  747.                     if (pen_usage_count[j] > max &&
  748.                             rr == (shrinked_palette[3*j + 0] >> 2) &&
  749.                             gg == (shrinked_palette[3*j + 1] >> 2) &&
  750.                             bb == (shrinked_palette[3*j + 2] >> 2))
  751.                     {
  752.                         rgb6_to_pen[rr][gg][bb] = j;
  753.                         max = pen_usage_count[j];
  754.                     }
  755.                 }
  756.             }
  757.         }
  758.     }
  759. }
  760.  
  761. static int compress_palette(void)
  762. {
  763.     int i,j,saved,r,g,b;
  764.  
  765.  
  766.     build_rgb_to_pen();
  767.  
  768.     saved = 0;
  769.  
  770.     for (i = 0;i < Machine->drv->total_colors;i++)
  771.     {
  772.         /* merge pens of the same color */
  773.         if ((old_used_colors[i] & PALETTE_COLOR_VISIBLE) &&
  774.                 !(old_used_colors[i] & (PALETTE_COLOR_NEEDS_REMAP|PALETTE_COLOR_TRANSPARENT_FLAG)))
  775.         {
  776.             r = game_palette[3*i + 0] >> 2;
  777.             g = game_palette[3*i + 1] >> 2;
  778.             b = game_palette[3*i + 2] >> 2;
  779.  
  780.             j = rgb6_to_pen[r][g][b];
  781.  
  782.             if (palette_map[i] != j)
  783.             {
  784.                 just_remapped[i] = 1;
  785.  
  786.                 pen_usage_count[palette_map[i]]--;
  787.                 if (pen_usage_count[palette_map[i]] == 0)
  788.                     saved++;
  789.                 palette_map[i] = j;
  790.                 pen_usage_count[palette_map[i]]++;
  791.                 Machine->pens[i] = shrinked_pens[palette_map[i]];
  792.             }
  793.         }
  794.     }
  795.  
  796. #if VERBOSE
  797. {
  798.     int subcount[8];
  799.  
  800.  
  801.     for (i = 0;i < 8;i++)
  802.         subcount[i] = 0;
  803.  
  804.     for (i = 0;i < Machine->drv->total_colors;i++)
  805.         subcount[palette_used_colors[i]]++;
  806.  
  807.     logerror("Ran out of pens! %d colors used (%d unused, %d visible %d cached %d visible+cached, %d transparent)\n",
  808.             subcount[PALETTE_COLOR_VISIBLE]+subcount[PALETTE_COLOR_CACHED]+subcount[PALETTE_COLOR_VISIBLE|PALETTE_COLOR_CACHED]+subcount[PALETTE_COLOR_TRANSPARENT],
  809.             subcount[PALETTE_COLOR_UNUSED],
  810.             subcount[PALETTE_COLOR_VISIBLE],
  811.             subcount[PALETTE_COLOR_CACHED],
  812.             subcount[PALETTE_COLOR_VISIBLE|PALETTE_COLOR_CACHED],
  813.             subcount[PALETTE_COLOR_TRANSPARENT]);
  814.     logerror("Compressed the palette, saving %d pens\n",saved);
  815. }
  816. #endif
  817.  
  818.     return saved;
  819. }
  820.  
  821.  
  822. static const unsigned char *palette_recalc_16_static(void)
  823. {
  824.     int i,color;
  825.     int did_remap = 0;
  826.     int need_refresh = 0;
  827.  
  828.  
  829.     memset(just_remapped,0,Machine->drv->total_colors * sizeof(unsigned char));
  830.  
  831.     for (color = 0;color < Machine->drv->total_colors;color++)
  832.     {
  833.         /* the comparison between palette_used_colors and old_used_colors also includes */
  834.         /* PALETTE_COLOR_NEEDS_REMAP which might have been set by palette_change_color() */
  835.         if ((palette_used_colors[color] & PALETTE_COLOR_VISIBLE) &&
  836.                 palette_used_colors[color] != old_used_colors[color])
  837.         {
  838.             int r,g,b;
  839.  
  840.  
  841.             did_remap = 1;
  842.             if (old_used_colors[color] & palette_used_colors[color] & PALETTE_COLOR_CACHED)
  843.             {
  844.                 /* the color was and still is cached, we'll have to redraw everything */
  845.                 need_refresh = 1;
  846.                 just_remapped[color] = 1;
  847.             }
  848.  
  849.             if (palette_used_colors[color] & PALETTE_COLOR_TRANSPARENT_FLAG)
  850.                 Machine->pens[color] = palette_transparent_pen;
  851.             else
  852.             {
  853.                 r = game_palette[3*color + 0];
  854.                 g = game_palette[3*color + 1];
  855.                 b = game_palette[3*color + 2];
  856.  
  857.                 Machine->pens[color] = shrinked_pens[rgbpenindex(r,g,b)];
  858.             }
  859.         }
  860.  
  861.         old_used_colors[color] = palette_used_colors[color];
  862.     }
  863.  
  864.  
  865.     if (did_remap)
  866.     {
  867.         /* rebuild the color lookup table */
  868.         for (i = 0;i < Machine->drv->color_table_len;i++)
  869.             Machine->remapped_colortable[i] = Machine->pens[Machine->game_colortable[i]];
  870.     }
  871.  
  872.     if (need_refresh) return just_remapped;
  873.     else return 0;
  874. }
  875.  
  876. static const unsigned char *palette_recalc_16_palettized(void)
  877. {
  878.     int i,color;
  879.     int did_remap = 0;
  880.     int need_refresh = 0;
  881.  
  882.  
  883.     memset(just_remapped,0,Machine->drv->total_colors * sizeof(unsigned char));
  884.  
  885.     for (color = 0;color < Machine->drv->total_colors;color++)
  886.     {
  887.         if ((palette_used_colors[color] & PALETTE_COLOR_TRANSPARENT_FLAG) !=
  888.                 (old_used_colors[color] & PALETTE_COLOR_TRANSPARENT_FLAG))
  889.         {
  890.             did_remap = 1;
  891.             if (old_used_colors[color] & palette_used_colors[color] & PALETTE_COLOR_CACHED)
  892.             {
  893.                 /* the color was and still is cached, we'll have to redraw everything */
  894.                 need_refresh = 1;
  895.                 just_remapped[color] = 1;
  896.             }
  897.  
  898.             if (palette_used_colors[color] & PALETTE_COLOR_TRANSPARENT_FLAG)
  899.                 Machine->pens[color] = palette_transparent_pen;
  900.             else
  901.                 Machine->pens[color] = shrinked_pens[color + RESERVED_PENS];
  902.         }
  903.  
  904.         old_used_colors[color] = palette_used_colors[color];
  905.     }
  906.  
  907.  
  908.     if (did_remap)
  909.     {
  910.         /* rebuild the color lookup table */
  911.         for (i = 0;i < Machine->drv->color_table_len;i++)
  912.             Machine->remapped_colortable[i] = Machine->pens[Machine->game_colortable[i]];
  913.     }
  914.  
  915.     if (need_refresh) return just_remapped;
  916.     else return 0;
  917. }
  918.  
  919. static const unsigned char *palette_recalc_8(void)
  920. {
  921.     int i,color;
  922.     int did_remap = 0;
  923.     int need_refresh = 0;
  924.     int first_free_pen;
  925.     int ran_out = 0;
  926.     int reuse_pens = 0;
  927.     int need,avail;
  928.  
  929.  
  930.     memset(just_remapped,0,Machine->drv->total_colors * sizeof(unsigned char));
  931.  
  932.  
  933.     /* first of all, apply the changes to the palette which were */
  934.     /* requested since last update */
  935.     for (color = 0;color < Machine->drv->total_colors;color++)
  936.     {
  937.         if (palette_dirty[color])
  938.         {
  939.             int r,g,b,pen;
  940.  
  941.  
  942.             pen = palette_map[color];
  943.             r = new_palette[3*color + 0];
  944.             g = new_palette[3*color + 1];
  945.             b = new_palette[3*color + 2];
  946.  
  947.             /* if the color maps to an exclusive pen, just change it */
  948.             if (pen_usage_count[pen] == 1)
  949.             {
  950.                 palette_dirty[color] = 0;
  951.                 game_palette[3*color + 0] = r;
  952.                 game_palette[3*color + 1] = g;
  953.                 game_palette[3*color + 2] = b;
  954.  
  955.                 shrinked_palette[3*pen + 0] = r;
  956.                 shrinked_palette[3*pen + 1] = g;
  957.                 shrinked_palette[3*pen + 2] = b;
  958.                 osd_modify_pen(Machine->pens[color],r,g,b);
  959.             }
  960.             else
  961.             {
  962.                 if (pen < RESERVED_PENS)
  963.                 {
  964.                     /* the color uses a reserved pen, the only thing we can do is remap it */
  965.                     for (i = color;i < Machine->drv->total_colors;i++)
  966.                     {
  967.                         if (palette_dirty[i] != 0 && palette_map[i] == pen)
  968.                         {
  969.                             palette_dirty[i] = 0;
  970.                             game_palette[3*i + 0] = new_palette[3*i + 0];
  971.                             game_palette[3*i + 1] = new_palette[3*i + 1];
  972.                             game_palette[3*i + 2] = new_palette[3*i + 2];
  973.                             old_used_colors[i] |= PALETTE_COLOR_NEEDS_REMAP;
  974.                         }
  975.                     }
  976.                 }
  977.                 else
  978.                 {
  979.                     /* the pen is shared with other colors, let's see if all of them */
  980.                     /* have been changed to the same value */
  981.                     for (i = 0;i < Machine->drv->total_colors;i++)
  982.                     {
  983.                         if ((old_used_colors[i] & PALETTE_COLOR_VISIBLE) &&
  984.                                 palette_map[i] == pen)
  985.                         {
  986.                             if (palette_dirty[i] == 0 ||
  987.                                     new_palette[3*i + 0] != r ||
  988.                                     new_palette[3*i + 1] != g ||
  989.                                     new_palette[3*i + 2] != b)
  990.                                 break;
  991.                         }
  992.                     }
  993.  
  994.                     if (i == Machine->drv->total_colors)
  995.                     {
  996.                         /* all colors sharing this pen still are the same, so we */
  997.                         /* just change the palette. */
  998.                         shrinked_palette[3*pen + 0] = r;
  999.                         shrinked_palette[3*pen + 1] = g;
  1000.                         shrinked_palette[3*pen + 2] = b;
  1001.                         osd_modify_pen(Machine->pens[color],r,g,b);
  1002.  
  1003.                         for (i = color;i < Machine->drv->total_colors;i++)
  1004.                         {
  1005.                             if (palette_dirty[i] != 0 && palette_map[i] == pen)
  1006.                             {
  1007.                                 palette_dirty[i] = 0;
  1008.                                 game_palette[3*i + 0] = r;
  1009.                                 game_palette[3*i + 1] = g;
  1010.                                 game_palette[3*i + 2] = b;
  1011.                             }
  1012.                         }
  1013.                     }
  1014.                     else
  1015.                     {
  1016.                         /* the colors sharing this pen now are different, we'll */
  1017.                         /* have to remap them. */
  1018.                         for (i = color;i < Machine->drv->total_colors;i++)
  1019.                         {
  1020.                             if (palette_dirty[i] != 0 && palette_map[i] == pen)
  1021.                             {
  1022.                                 palette_dirty[i] = 0;
  1023.                                 game_palette[3*i + 0] = new_palette[3*i + 0];
  1024.                                 game_palette[3*i + 1] = new_palette[3*i + 1];
  1025.                                 game_palette[3*i + 2] = new_palette[3*i + 2];
  1026.                                 old_used_colors[i] |= PALETTE_COLOR_NEEDS_REMAP;
  1027.                             }
  1028.                         }
  1029.                     }
  1030.                 }
  1031.             }
  1032.         }
  1033.     }
  1034.  
  1035.  
  1036.     need = 0;
  1037.     for (i = 0;i < Machine->drv->total_colors;i++)
  1038.     {
  1039.         if ((palette_used_colors[i] & PALETTE_COLOR_VISIBLE) && palette_used_colors[i] != old_used_colors[i])
  1040.             need++;
  1041.     }
  1042.     if (need > 0)
  1043.     {
  1044.         avail = 0;
  1045.         for (i = 0;i < DYNAMIC_MAX_PENS;i++)
  1046.         {
  1047.             if (pen_usage_count[i] == 0)
  1048.                 avail++;
  1049.         }
  1050.  
  1051.         if (need > avail)
  1052.         {
  1053. #if VERBOSE
  1054. logerror("Need %d new pens; %d available. I'll reuse some pens.\n",need,avail);
  1055. #endif
  1056.             reuse_pens = 1;
  1057.             build_rgb_to_pen();
  1058.         }
  1059.     }
  1060.  
  1061.     first_free_pen = RESERVED_PENS;
  1062.     for (color = 0;color < Machine->drv->total_colors;color++)
  1063.     {
  1064.         /* the comparison between palette_used_colors and old_used_colors also includes */
  1065.         /* PALETTE_COLOR_NEEDS_REMAP which might have been set previously */
  1066.         if ((palette_used_colors[color] & PALETTE_COLOR_VISIBLE) &&
  1067.                 palette_used_colors[color] != old_used_colors[color])
  1068.         {
  1069.             int r,g,b;
  1070.  
  1071.  
  1072.             if (old_used_colors[color] & PALETTE_COLOR_VISIBLE)
  1073.             {
  1074.                 pen_usage_count[palette_map[color]]--;
  1075.                 old_used_colors[color] &= ~PALETTE_COLOR_VISIBLE;
  1076.             }
  1077.  
  1078.             r = game_palette[3*color + 0];
  1079.             g = game_palette[3*color + 1];
  1080.             b = game_palette[3*color + 2];
  1081.  
  1082.             if (palette_used_colors[color] & PALETTE_COLOR_TRANSPARENT_FLAG)
  1083.             {
  1084.                 if (palette_map[color] != TRANSPARENT_PEN)
  1085.                 {
  1086.                     /* use the fixed transparent black for this */
  1087.                     did_remap = 1;
  1088.                     if (old_used_colors[color] & palette_used_colors[color] & PALETTE_COLOR_CACHED)
  1089.                     {
  1090.                         /* the color was and still is cached, we'll have to redraw everything */
  1091.                         need_refresh = 1;
  1092.                         just_remapped[color] = 1;
  1093.                     }
  1094.  
  1095.                     palette_map[color] = TRANSPARENT_PEN;
  1096.                 }
  1097.                 pen_usage_count[palette_map[color]]++;
  1098.                 Machine->pens[color] = shrinked_pens[palette_map[color]];
  1099.                 old_used_colors[color] = palette_used_colors[color];
  1100.             }
  1101.             else
  1102.             {
  1103.                 if (reuse_pens)
  1104.                 {
  1105.                     i = rgb6_to_pen[r >> 2][g >> 2][b >> 2];
  1106.                     if (i != DYNAMIC_MAX_PENS)
  1107.                     {
  1108.                         if (palette_map[color] != i)
  1109.                         {
  1110.                             did_remap = 1;
  1111.                             if (old_used_colors[color] & palette_used_colors[color] & PALETTE_COLOR_CACHED)
  1112.                             {
  1113.                                 /* the color was and still is cached, we'll have to redraw everything */
  1114.                                 need_refresh = 1;
  1115.                                 just_remapped[color] = 1;
  1116.                             }
  1117.  
  1118.                             palette_map[color] = i;
  1119.                         }
  1120.                         pen_usage_count[palette_map[color]]++;
  1121.                         Machine->pens[color] = shrinked_pens[palette_map[color]];
  1122.                         old_used_colors[color] = palette_used_colors[color];
  1123.                     }
  1124.                 }
  1125.  
  1126.                 /* if we still haven't found a pen, choose a new one */
  1127.                 if (old_used_colors[color] != palette_used_colors[color])
  1128.                 {
  1129.                     /* if possible, reuse the last associated pen */
  1130.                     if (pen_usage_count[palette_map[color]] == 0)
  1131.                     {
  1132.                         pen_usage_count[palette_map[color]]++;
  1133.                     }
  1134.                     else    /* allocate a new pen */
  1135.                     {
  1136. retry:
  1137.                         while (first_free_pen < DYNAMIC_MAX_PENS && pen_usage_count[first_free_pen] > 0)
  1138.                             first_free_pen++;
  1139.  
  1140.                         if (first_free_pen < DYNAMIC_MAX_PENS)
  1141.                         {
  1142.                             did_remap = 1;
  1143.                             if (old_used_colors[color] & palette_used_colors[color] & PALETTE_COLOR_CACHED)
  1144.                             {
  1145.                                 /* the color was and still is cached, we'll have to redraw everything */
  1146.                                 need_refresh = 1;
  1147.                                 just_remapped[color] = 1;
  1148.                             }
  1149.  
  1150.                             palette_map[color] = first_free_pen;
  1151.                             pen_usage_count[palette_map[color]]++;
  1152.                             Machine->pens[color] = shrinked_pens[palette_map[color]];
  1153.                         }
  1154.                         else
  1155.                         {
  1156.                             /* Ran out of pens! Let's see what we can do. */
  1157.  
  1158.                             if (ran_out == 0)
  1159.                             {
  1160.                                 ran_out++;
  1161.  
  1162.                                 /* from now on, try to reuse already allocated pens */
  1163.                                 reuse_pens = 1;
  1164.                                 if (compress_palette() > 0)
  1165.                                 {
  1166.                                     did_remap = 1;
  1167.                                     need_refresh = 1;    /* we'll have to redraw everything */
  1168.  
  1169.                                     first_free_pen = RESERVED_PENS;
  1170.                                     goto retry;
  1171.                                 }
  1172.                             }
  1173.  
  1174.                             ran_out++;
  1175.  
  1176.                             /* we failed, but go on with the loop, there might */
  1177.                             /* be some transparent pens to remap */
  1178.  
  1179.                             continue;
  1180.                         }
  1181.                     }
  1182.  
  1183.                     {
  1184.                         int rr,gg,bb;
  1185.  
  1186.                         i = palette_map[color];
  1187.                         rr = shrinked_palette[3*i + 0] >> 2;
  1188.                         gg = shrinked_palette[3*i + 1] >> 2;
  1189.                         bb = shrinked_palette[3*i + 2] >> 2;
  1190.                         if (rgb6_to_pen[rr][gg][bb] == i)
  1191.                             rgb6_to_pen[rr][gg][bb] = DYNAMIC_MAX_PENS;
  1192.  
  1193.                         shrinked_palette[3*i + 0] = r;
  1194.                         shrinked_palette[3*i + 1] = g;
  1195.                         shrinked_palette[3*i + 2] = b;
  1196.                         osd_modify_pen(Machine->pens[color],r,g,b);
  1197.  
  1198.                         r >>= 2;
  1199.                         g >>= 2;
  1200.                         b >>= 2;
  1201.                         if (rgb6_to_pen[r][g][b] == DYNAMIC_MAX_PENS)
  1202.                             rgb6_to_pen[r][g][b] = i;
  1203.                     }
  1204.  
  1205.                     old_used_colors[color] = palette_used_colors[color];
  1206.                 }
  1207.             }
  1208.         }
  1209.     }
  1210.  
  1211.     if (ran_out > 1)
  1212.     {
  1213. #ifdef MAME_DEBUG
  1214.         char buf[80];
  1215.  
  1216.         sprintf(buf,"Error: Palette overflow -%d",ran_out-1);
  1217.         usrintf_showmessage(buf);
  1218. #endif
  1219. logerror("Error: no way to shrink the palette to 256 colors, left out %d colors.\n",ran_out-1);
  1220. #if 0
  1221. logerror("color list:\n");
  1222. for (color = 0;color < Machine->drv->total_colors;color++)
  1223. {
  1224.     int r,g,b;
  1225.     r = game_palette[3*color + 0];
  1226.     g = game_palette[3*color + 1];
  1227.     b = game_palette[3*color + 2];
  1228.     if (palette_used_colors[color] & PALETTE_COLOR_VISIBLE)
  1229.         logerror("%02x %02x %02x\n",r,g,b);
  1230. }
  1231. #endif
  1232.     }
  1233.  
  1234.     /* Reclaim unused pens; we do this AFTER allocating the new ones, to avoid */
  1235.     /* using the same pen for two different colors in two consecutive frames, */
  1236.     /* which might cause flicker. */
  1237.     for (color = 0;color < Machine->drv->total_colors;color++)
  1238.     {
  1239.         if (!(palette_used_colors[color] & PALETTE_COLOR_VISIBLE))
  1240.         {
  1241.             if (old_used_colors[color] & PALETTE_COLOR_VISIBLE)
  1242.                 pen_usage_count[palette_map[color]]--;
  1243.             old_used_colors[color] = palette_used_colors[color];
  1244.         }
  1245.     }
  1246.  
  1247. #ifdef PEDANTIC
  1248.     /* invalidate unused pens to make bugs in color allocation evident. */
  1249.     for (i = 0;i < DYNAMIC_MAX_PENS;i++)
  1250.     {
  1251.         if (pen_usage_count[i] == 0)
  1252.         {
  1253.             int r,g,b;
  1254.             r = rand() & 0xff;
  1255.             g = rand() & 0xff;
  1256.             b = rand() & 0xff;
  1257.             shrinked_palette[3*i + 0] = r;
  1258.             shrinked_palette[3*i + 1] = g;
  1259.             shrinked_palette[3*i + 2] = b;
  1260.             osd_modify_pen(shrinked_pens[i],r,g,b);
  1261.         }
  1262.     }
  1263. #endif
  1264.  
  1265.     if (did_remap)
  1266.     {
  1267.         /* rebuild the color lookup table */
  1268.         for (i = 0;i < Machine->drv->color_table_len;i++)
  1269.             Machine->remapped_colortable[i] = Machine->pens[Machine->game_colortable[i]];
  1270.     }
  1271.  
  1272.     if (need_refresh)
  1273.     {
  1274. #if VERBOSE
  1275.         int used;
  1276.  
  1277.         used = 0;
  1278.         for (i = 0;i < DYNAMIC_MAX_PENS;i++)
  1279.         {
  1280.             if (pen_usage_count[i] > 0)
  1281.                 used++;
  1282.         }
  1283.         logerror("Did a palette remap, need a full screen redraw (%d pens used).\n",used);
  1284. #endif
  1285.  
  1286.         return just_remapped;
  1287.     }
  1288.     else return 0;
  1289. }
  1290.  
  1291.  
  1292. const unsigned char *palette_recalc(void)
  1293. {
  1294.     const unsigned char* ret = NULL;
  1295.  
  1296.     /* if we are not dynamically reducing the palette, return NULL. */
  1297.     if (palette_used_colors != 0)
  1298.     {
  1299.         switch (use_16bit)
  1300.         {
  1301.             case NO_16BIT:
  1302.             default:
  1303.                 ret = palette_recalc_8();
  1304.                 break;
  1305.             case STATIC_16BIT:
  1306.                 ret = palette_recalc_16_static();
  1307.                 break;
  1308.             case PALETTIZED_16BIT:
  1309.                 ret = palette_recalc_16_palettized();
  1310.                 break;
  1311.         }
  1312.     }
  1313.  
  1314.     if (ret) overlay_remap();
  1315.  
  1316.     return ret;
  1317. }
  1318.  
  1319.  
  1320.  
  1321. /******************************************************************************
  1322.  
  1323.  Commonly used palette RAM handling functions
  1324.  
  1325. ******************************************************************************/
  1326.  
  1327. unsigned char *paletteram,*paletteram_2;
  1328.  
  1329. READ_HANDLER( paletteram_r )
  1330. {
  1331.     return paletteram[offset];
  1332. }
  1333.  
  1334. READ_HANDLER( paletteram_2_r )
  1335. {
  1336.     return paletteram_2[offset];
  1337. }
  1338.  
  1339. READ_HANDLER( paletteram_word_r )
  1340. {
  1341.     return READ_WORD(&paletteram[offset]);
  1342. }
  1343.  
  1344. READ_HANDLER( paletteram_2_word_r )
  1345. {
  1346.     return READ_WORD(&paletteram_2[offset]);
  1347. }
  1348.  
  1349. WRITE_HANDLER( paletteram_RRRGGGBB_w )
  1350. {
  1351.     int r,g,b;
  1352.     int bit0,bit1,bit2;
  1353.  
  1354.  
  1355.     paletteram[offset] = data;
  1356.  
  1357.     /* red component */
  1358.     bit0 = (data >> 5) & 0x01;
  1359.     bit1 = (data >> 6) & 0x01;
  1360.     bit2 = (data >> 7) & 0x01;
  1361.     r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  1362.     /* green component */
  1363.     bit0 = (data >> 2) & 0x01;
  1364.     bit1 = (data >> 3) & 0x01;
  1365.     bit2 = (data >> 4) & 0x01;
  1366.     g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  1367.     /* blue component */
  1368.     bit0 = 0;
  1369.     bit1 = (data >> 0) & 0x01;
  1370.     bit2 = (data >> 1) & 0x01;
  1371.     b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  1372.  
  1373.     palette_change_color(offset,r,g,b);
  1374. }
  1375.  
  1376.  
  1377. WRITE_HANDLER( paletteram_BBGGGRRR_w )
  1378. {
  1379.     int r,g,b;
  1380.     int bit0,bit1,bit2;
  1381.  
  1382.  
  1383.     paletteram[offset] = data;
  1384.  
  1385.     /* red component */
  1386.     bit0 = (data >> 0) & 0x01;
  1387.     bit1 = (data >> 1) & 0x01;
  1388.     bit2 = (data >> 2) & 0x01;
  1389.     r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  1390.     /* green component */
  1391.     bit0 = (data >> 3) & 0x01;
  1392.     bit1 = (data >> 4) & 0x01;
  1393.     bit2 = (data >> 5) & 0x01;
  1394.     g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  1395.     /* blue component */
  1396.     bit0 = 0;
  1397.     bit1 = (data >> 6) & 0x01;
  1398.     bit2 = (data >> 7) & 0x01;
  1399.     b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
  1400.  
  1401.     palette_change_color(offset,r,g,b);
  1402. }
  1403.  
  1404.  
  1405. WRITE_HANDLER( paletteram_IIBBGGRR_w )
  1406. {
  1407.     int r,g,b,i;
  1408.  
  1409.  
  1410.     paletteram[offset] = data;
  1411.  
  1412.     i = (data >> 6) & 0x03;
  1413.     /* red component */
  1414.     r = (data << 2) & 0x0c;
  1415.     if (r) r |= i;
  1416.     r *= 0x11;
  1417.     /* green component */
  1418.     g = (data >> 0) & 0x0c;
  1419.     if (g) g |= i;
  1420.     g *= 0x11;
  1421.     /* blue component */
  1422.     b = (data >> 2) & 0x0c;
  1423.     if (b) b |= i;
  1424.     b *= 0x11;
  1425.  
  1426.     palette_change_color(offset,r,g,b);
  1427. }
  1428.  
  1429.  
  1430. WRITE_HANDLER( paletteram_BBGGRRII_w )
  1431. {
  1432.     int r,g,b,i;
  1433.  
  1434.  
  1435.     paletteram[offset] = data;
  1436.  
  1437.     i = (data >> 0) & 0x03;
  1438.     /* red component */
  1439.     r = (((data >> 0) & 0x0c) | i) * 0x11;
  1440.     /* green component */
  1441.     g = (((data >> 2) & 0x0c) | i) * 0x11;
  1442.     /* blue component */
  1443.     b = (((data >> 4) & 0x0c) | i) * 0x11;
  1444.  
  1445.     palette_change_color(offset,r,g,b);
  1446. }
  1447.  
  1448.  
  1449. INLINE void changecolor_xxxxBBBBGGGGRRRR(int color,int data)
  1450. {
  1451.     int r,g,b;
  1452.  
  1453.  
  1454.     r = (data >> 0) & 0x0f;
  1455.     g = (data >> 4) & 0x0f;
  1456.     b = (data >> 8) & 0x0f;
  1457.  
  1458.     r = (r << 4) | r;
  1459.     g = (g << 4) | g;
  1460.     b = (b << 4) | b;
  1461.  
  1462.     palette_change_color(color,r,g,b);
  1463. }
  1464.  
  1465. WRITE_HANDLER( paletteram_xxxxBBBBGGGGRRRR_w )
  1466. {
  1467.     paletteram[offset] = data;
  1468.     changecolor_xxxxBBBBGGGGRRRR(offset / 2,paletteram[offset & ~1] | (paletteram[offset | 1] << 8));
  1469. }
  1470.  
  1471. WRITE_HANDLER( paletteram_xxxxBBBBGGGGRRRR_swap_w )
  1472. {
  1473.     paletteram[offset] = data;
  1474.     changecolor_xxxxBBBBGGGGRRRR(offset / 2,paletteram[offset | 1] | (paletteram[offset & ~1] << 8));
  1475. }
  1476.  
  1477. WRITE_HANDLER( paletteram_xxxxBBBBGGGGRRRR_split1_w )
  1478. {
  1479.     paletteram[offset] = data;
  1480.     changecolor_xxxxBBBBGGGGRRRR(offset,paletteram[offset] | (paletteram_2[offset] << 8));
  1481. }
  1482.  
  1483. WRITE_HANDLER( paletteram_xxxxBBBBGGGGRRRR_split2_w )
  1484. {
  1485.     paletteram_2[offset] = data;
  1486.     changecolor_xxxxBBBBGGGGRRRR(offset,paletteram[offset] | (paletteram_2[offset] << 8));
  1487. }
  1488.  
  1489. WRITE_HANDLER( paletteram_xxxxBBBBGGGGRRRR_word_w )
  1490. {
  1491.     int oldword = READ_WORD(&paletteram[offset]);
  1492.     int newword = COMBINE_WORD(oldword,data);
  1493.  
  1494.  
  1495.     WRITE_WORD(&paletteram[offset],newword);
  1496.     changecolor_xxxxBBBBGGGGRRRR(offset / 2,newword);
  1497. }
  1498.  
  1499.  
  1500. INLINE void changecolor_xxxxBBBBRRRRGGGG(int color,int data)
  1501. {
  1502.     int r,g,b;
  1503.  
  1504.  
  1505.     r = (data >> 4) & 0x0f;
  1506.     g = (data >> 0) & 0x0f;
  1507.     b = (data >> 8) & 0x0f;
  1508.  
  1509.     r = (r << 4) | r;
  1510.     g = (g << 4) | g;
  1511.     b = (b << 4) | b;
  1512.  
  1513.     palette_change_color(color,r,g,b);
  1514. }
  1515.  
  1516. WRITE_HANDLER( paletteram_xxxxBBBBRRRRGGGG_w )
  1517. {
  1518.     paletteram[offset] = data;
  1519.     changecolor_xxxxBBBBRRRRGGGG(offset / 2,paletteram[offset & ~1] | (paletteram[offset | 1] << 8));
  1520. }
  1521.  
  1522. WRITE_HANDLER( paletteram_xxxxBBBBRRRRGGGG_swap_w )
  1523. {
  1524.     paletteram[offset] = data;
  1525.     changecolor_xxxxBBBBRRRRGGGG(offset / 2,paletteram[offset | 1] | (paletteram[offset & ~1] << 8));
  1526. }
  1527.  
  1528. WRITE_HANDLER( paletteram_xxxxBBBBRRRRGGGG_split1_w )
  1529. {
  1530.     paletteram[offset] = data;
  1531.     changecolor_xxxxBBBBRRRRGGGG(offset,paletteram[offset] | (paletteram_2[offset] << 8));
  1532. }
  1533.  
  1534. WRITE_HANDLER( paletteram_xxxxBBBBRRRRGGGG_split2_w )
  1535. {
  1536.     paletteram_2[offset] = data;
  1537.     changecolor_xxxxBBBBRRRRGGGG(offset,paletteram[offset] | (paletteram_2[offset] << 8));
  1538. }
  1539.  
  1540.  
  1541. INLINE void changecolor_xxxxRRRRBBBBGGGG(int color,int data)
  1542. {
  1543.     int r,g,b;
  1544.  
  1545.  
  1546.     r = (data >> 8) & 0x0f;
  1547.     g = (data >> 0) & 0x0f;
  1548.     b = (data >> 4) & 0x0f;
  1549.  
  1550.     r = (r << 4) | r;
  1551.     g = (g << 4) | g;
  1552.     b = (b << 4) | b;
  1553.  
  1554.     palette_change_color(color,r,g,b);
  1555. }
  1556.  
  1557. WRITE_HANDLER( paletteram_xxxxRRRRBBBBGGGG_split1_w )
  1558. {
  1559.     paletteram[offset] = data;
  1560.     changecolor_xxxxRRRRBBBBGGGG(offset,paletteram[offset] | (paletteram_2[offset] << 8));
  1561. }
  1562.  
  1563. WRITE_HANDLER( paletteram_xxxxRRRRBBBBGGGG_split2_w )
  1564. {
  1565.     paletteram_2[offset] = data;
  1566.     changecolor_xxxxRRRRBBBBGGGG(offset,paletteram[offset] | (paletteram_2[offset] << 8));
  1567. }
  1568.  
  1569.  
  1570. INLINE void changecolor_xxxxRRRRGGGGBBBB(int color,int data)
  1571. {
  1572.     int r,g,b;
  1573.  
  1574.  
  1575.     r = (data >> 8) & 0x0f;
  1576.     g = (data >> 4) & 0x0f;
  1577.     b = (data >> 0) & 0x0f;
  1578.  
  1579.     r = (r << 4) | r;
  1580.     g = (g << 4) | g;
  1581.     b = (b << 4) | b;
  1582.  
  1583.     palette_change_color(color,r,g,b);
  1584. }
  1585.  
  1586. WRITE_HANDLER( paletteram_xxxxRRRRGGGGBBBB_w )
  1587. {
  1588.     paletteram[offset] = data;
  1589.     changecolor_xxxxRRRRGGGGBBBB(offset / 2,paletteram[offset & ~1] | (paletteram[offset | 1] << 8));
  1590. }
  1591.  
  1592. WRITE_HANDLER( paletteram_xxxxRRRRGGGGBBBB_word_w )
  1593. {
  1594.     int oldword = READ_WORD(&paletteram[offset]);
  1595.     int newword = COMBINE_WORD(oldword,data);
  1596.  
  1597.  
  1598.     WRITE_WORD(&paletteram[offset],newword);
  1599.     changecolor_xxxxRRRRGGGGBBBB(offset / 2,newword);
  1600. }
  1601.  
  1602.  
  1603. INLINE void changecolor_RRRRGGGGBBBBxxxx(int color,int data)
  1604. {
  1605.     int r,g,b;
  1606.  
  1607.  
  1608.     r = (data >> 12) & 0x0f;
  1609.     g = (data >>  8) & 0x0f;
  1610.     b = (data >>  4) & 0x0f;
  1611.  
  1612.     r = (r << 4) | r;
  1613.     g = (g << 4) | g;
  1614.     b = (b << 4) | b;
  1615.  
  1616.     palette_change_color(color,r,g,b);
  1617. }
  1618.  
  1619. WRITE_HANDLER( paletteram_RRRRGGGGBBBBxxxx_swap_w )
  1620. {
  1621.     paletteram[offset] = data;
  1622.     changecolor_RRRRGGGGBBBBxxxx(offset / 2,paletteram[offset | 1] | (paletteram[offset & ~1] << 8));
  1623. }
  1624.  
  1625. WRITE_HANDLER( paletteram_RRRRGGGGBBBBxxxx_split1_w )
  1626. {
  1627.     paletteram[offset] = data;
  1628.     changecolor_RRRRGGGGBBBBxxxx(offset,paletteram[offset] | (paletteram_2[offset] << 8));
  1629. }
  1630.  
  1631. WRITE_HANDLER( paletteram_RRRRGGGGBBBBxxxx_split2_w )
  1632. {
  1633.     paletteram_2[offset] = data;
  1634.     changecolor_RRRRGGGGBBBBxxxx(offset,paletteram[offset] | (paletteram_2[offset] << 8));
  1635. }
  1636.  
  1637. WRITE_HANDLER( paletteram_RRRRGGGGBBBBxxxx_word_w )
  1638. {
  1639.     int oldword = READ_WORD(&paletteram[offset]);
  1640.     int newword = COMBINE_WORD(oldword,data);
  1641.  
  1642.  
  1643.     WRITE_WORD(&paletteram[offset],newword);
  1644.     changecolor_RRRRGGGGBBBBxxxx(offset / 2,newword);
  1645. }
  1646.  
  1647.  
  1648. INLINE void changecolor_BBBBGGGGRRRRxxxx(int color,int data)
  1649. {
  1650.     int r,g,b;
  1651.  
  1652.  
  1653.     r = (data >>  4) & 0x0f;
  1654.     g = (data >>  8) & 0x0f;
  1655.     b = (data >> 12) & 0x0f;
  1656.  
  1657.     r = (r << 4) | r;
  1658.     g = (g << 4) | g;
  1659.     b = (b << 4) | b;
  1660.  
  1661.     palette_change_color(color,r,g,b);
  1662. }
  1663.  
  1664. WRITE_HANDLER( paletteram_BBBBGGGGRRRRxxxx_swap_w )
  1665. {
  1666.     paletteram[offset] = data;
  1667.     changecolor_BBBBGGGGRRRRxxxx(offset / 2,paletteram[offset | 1] | (paletteram[offset & ~1] << 8));
  1668. }
  1669.  
  1670. WRITE_HANDLER( paletteram_BBBBGGGGRRRRxxxx_split1_w )
  1671. {
  1672.     paletteram[offset] = data;
  1673.     changecolor_BBBBGGGGRRRRxxxx(offset,paletteram[offset] | (paletteram_2[offset] << 8));
  1674. }
  1675.  
  1676. WRITE_HANDLER( paletteram_BBBBGGGGRRRRxxxx_split2_w )
  1677. {
  1678.     paletteram_2[offset] = data;
  1679.     changecolor_BBBBGGGGRRRRxxxx(offset,paletteram[offset] | (paletteram_2[offset] << 8));
  1680. }
  1681.  
  1682. WRITE_HANDLER( paletteram_BBBBGGGGRRRRxxxx_word_w )
  1683. {
  1684.     int oldword = READ_WORD(&paletteram[offset]);
  1685.     int newword = COMBINE_WORD(oldword,data);
  1686.  
  1687.  
  1688.     WRITE_WORD(&paletteram[offset],newword);
  1689.     changecolor_BBBBGGGGRRRRxxxx(offset / 2,newword);
  1690. }
  1691.  
  1692.  
  1693. INLINE void changecolor_xBBBBBGGGGGRRRRR(int color,int data)
  1694. {
  1695.     int r,g,b;
  1696.  
  1697.  
  1698.     r = (data >>  0) & 0x1f;
  1699.     g = (data >>  5) & 0x1f;
  1700.     b = (data >> 10) & 0x1f;
  1701.  
  1702.     r = (r << 3) | (r >> 2);
  1703.     g = (g << 3) | (g >> 2);
  1704.     b = (b << 3) | (b >> 2);
  1705.  
  1706.     palette_change_color(color,r,g,b);
  1707. }
  1708.  
  1709. WRITE_HANDLER( paletteram_xBBBBBGGGGGRRRRR_w )
  1710. {
  1711.     paletteram[offset] = data;
  1712.     changecolor_xBBBBBGGGGGRRRRR(offset / 2,paletteram[offset & ~1] | (paletteram[offset | 1] << 8));
  1713. }
  1714.  
  1715. WRITE_HANDLER( paletteram_xBBBBBGGGGGRRRRR_swap_w )
  1716. {
  1717.     paletteram[offset] = data;
  1718.     changecolor_xBBBBBGGGGGRRRRR(offset / 2,paletteram[offset | 1] | (paletteram[offset & ~1] << 8));
  1719. }
  1720.  
  1721. WRITE_HANDLER( paletteram_xBBBBBGGGGGRRRRR_word_w )
  1722. {
  1723.     int oldword = READ_WORD(&paletteram[offset]);
  1724.     int newword = COMBINE_WORD(oldword,data);
  1725.  
  1726.  
  1727.     WRITE_WORD(&paletteram[offset],newword);
  1728.     changecolor_xBBBBBGGGGGRRRRR(offset / 2,newword);
  1729. }
  1730.  
  1731.  
  1732. INLINE void changecolor_xRRRRRGGGGGBBBBB(int color,int data)
  1733. {
  1734.     int r,g,b;
  1735.  
  1736.  
  1737.     r = (data >> 10) & 0x1f;
  1738.     g = (data >>  5) & 0x1f;
  1739.     b = (data >>  0) & 0x1f;
  1740.  
  1741.     r = (r << 3) | (r >> 2);
  1742.     g = (g << 3) | (g >> 2);
  1743.     b = (b << 3) | (b >> 2);
  1744.  
  1745.     palette_change_color(color,r,g,b);
  1746. }
  1747.  
  1748. WRITE_HANDLER( paletteram_xRRRRRGGGGGBBBBB_w )
  1749. {
  1750.     paletteram[offset] = data;
  1751.     changecolor_xRRRRRGGGGGBBBBB(offset / 2,paletteram[offset & ~1] | (paletteram[offset | 1] << 8));
  1752. }
  1753.  
  1754. WRITE_HANDLER( paletteram_xRRRRRGGGGGBBBBB_word_w )
  1755. {
  1756.     int oldword = READ_WORD(&paletteram[offset]);
  1757.     int newword = COMBINE_WORD(oldword,data);
  1758.  
  1759.  
  1760.     WRITE_WORD(&paletteram[offset],newword);
  1761.     changecolor_xRRRRRGGGGGBBBBB(offset / 2,newword);
  1762. }
  1763.  
  1764.  
  1765. INLINE void changecolor_xGGGGGRRRRRBBBBB(int color,int data)
  1766. {
  1767.     int r,g,b;
  1768.  
  1769.  
  1770.     r = (data >>  5) & 0x1f;
  1771.     g = (data >> 10) & 0x1f;
  1772.     b = (data >>  0) & 0x1f;
  1773.  
  1774.     r = (r << 3) | (r >> 2);
  1775.     g = (g << 3) | (g >> 2);
  1776.     b = (b << 3) | (b >> 2);
  1777.  
  1778.     palette_change_color(color,r,g,b);
  1779. }
  1780.  
  1781. WRITE_HANDLER( paletteram_xGGGGGRRRRRBBBBB_word_w )
  1782. {
  1783.     int oldword = READ_WORD(&paletteram[offset]);
  1784.     int newword = COMBINE_WORD(oldword,data);
  1785.  
  1786.  
  1787.     WRITE_WORD(&paletteram[offset],newword);
  1788.     changecolor_xGGGGGRRRRRBBBBB(offset / 2,newword);
  1789. }
  1790.  
  1791.  
  1792. INLINE void changecolor_IIIIRRRRGGGGBBBB(int color,int data)
  1793. {
  1794.     int i,r,g,b;
  1795.  
  1796.  
  1797.     static const int ztable[16] =
  1798.         { 0x0, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11 };
  1799.  
  1800.     i = ztable[(data >> 12) & 15];
  1801.     r = ((data >> 8) & 15) * i;
  1802.     g = ((data >> 4) & 15) * i;
  1803.     b = ((data >> 0) & 15) * i;
  1804.  
  1805.     palette_change_color(color,r,g,b);
  1806. }
  1807.  
  1808. WRITE_HANDLER( paletteram_IIIIRRRRGGGGBBBB_word_w )
  1809. {
  1810.     int oldword = READ_WORD(&paletteram[offset]);
  1811.     int newword = COMBINE_WORD(oldword,data);
  1812.  
  1813.  
  1814.     WRITE_WORD(&paletteram[offset],newword);
  1815.     changecolor_IIIIRRRRGGGGBBBB(offset / 2,newword);
  1816. }
  1817.  
  1818.  
  1819. INLINE void changecolor_RRRRGGGGBBBBIIII(int color,int data)
  1820. {
  1821.     int i,r,g,b;
  1822.  
  1823.  
  1824.     static const int ztable[16] =
  1825.         { 0x0, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11 };
  1826.  
  1827.     i = ztable[(data >> 0) & 15];
  1828.     r = ((data >> 12) & 15) * i;
  1829.     g = ((data >>  8) & 15) * i;
  1830.     b = ((data >>  4) & 15) * i;
  1831.  
  1832.     palette_change_color(color,r,g,b);
  1833. }
  1834.  
  1835. WRITE_HANDLER( paletteram_RRRRGGGGBBBBIIII_word_w )
  1836. {
  1837.     int oldword = READ_WORD(&paletteram[offset]);
  1838.     int newword = COMBINE_WORD(oldword,data);
  1839.  
  1840.  
  1841.     WRITE_WORD(&paletteram[offset],newword);
  1842.     changecolor_RRRRGGGGBBBBIIII(offset / 2,newword);
  1843. }
  1844.